package com.sc.nft.controller;


import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.net.URLDecoder;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.sc.nft.annotation.UserLogin;
import com.sc.nft.annotation.WithoutSign;
import com.sc.nft.controller.request.*;
import com.sc.nft.dao.PayOrderDao;
import com.sc.nft.dto.BindPaySendSmsVO;
import com.sc.nft.dto.CommonPaymentDTO;
import com.sc.nft.entity.UserInfo;
import com.sc.nft.entity.vo.*;
import com.sc.nft.entity.vo.mall.MallPaymentMethodVO;
import com.sc.nft.enums.RedisKeyEnum;
import com.sc.nft.exception.GlobalException;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.helper.HfPayHelper;
import com.sc.nft.pool.UserPool;
import com.sc.nft.service.PayOrderService;
import com.sc.nft.service.PaymentMethodService;
import com.sc.nft.service.ScUserAccountFlowService;
import com.sc.nft.sup.ErrorCode;
import com.sc.nft.sup.Result;
import com.sc.nft.wrapper.RequestWrapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.nio.charset.Charset;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;


@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/payment")
@Api(tags = "支付接口")
public class PaymentController {

    private final PaymentMethodService paymentMethodService;
    private final PayOrderService payOrderService;
    private final PayOrderDao payOrderDao;
    private final Redisson redisson;
    private final ScUserAccountFlowService userAccountFlowService;


    @ApiOperation(value = "获取支付渠道限额", notes = "获取支付渠道限额", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/getChannelLimit", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<List<ChannelLimitVO>> getChannelLimit() {
        return Result.success(paymentMethodService.getChannelLimit());
    }

    @ApiOperation(value = "获取支付方式", notes = "获取支付方式", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/getPaymentMethods", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<List<PaymentMethodVO>> getPaymentMethods() {
        return Result.success(paymentMethodService.getEffectPayment());
    }

    @ApiOperation(value = "获取交易池支付方式", notes = "获取交易池支付方式", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/getTradingPoolPayMethod", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<List<PaymentMethodVO>> getTradingPoolPayMethod() {
        return Result.success(paymentMethodService.getTradingPoolPayMethod());
    }

    @ApiOperation(value = "获取支付方式(H5)", notes = "获取支付方式(H5)", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/getPaymentMethodsByWeb", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<List<PaymentMethodVO>> getPaymentMethodsByWeb() {
        return Result.success(paymentMethodService.getEffectPaymentWeb());
    }


    @ApiOperation(value = "获取二级支付方式", notes = "获取二级支付方式", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/getSecondPayment", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    @CrossOrigin
    public Result<List<MallPaymentMethodVO>> getSecondPayment() {
        return Result.success(paymentMethodService.getSecondPayMethods());
    }

    @ApiOperation(value = "获取二级权益道具支付方式", notes = "获取二级权益道具支付方式", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/getSecondEquityPropsPayment", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    @CrossOrigin
    public Result<List<MallPaymentMethodVO>> getSecondEquityPropsPayment() {
        return Result.success(paymentMethodService.getSecondEquityPropsPayment());
    }

    @ApiOperation(value = "获取支付方式(充值)", notes = "获取支付方式(充值)", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/getPaymentMethodsByRecharge", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<List<PaymentMethodVO>> getPaymentMethodsByRecharge(@Valid @RequestBody GetPaymentMethodsByRechargeRequest rechargeRequest) {
        boolean isH5 = rechargeRequest.getIsH5() != 0;//非0为true
        return Result.success(paymentMethodService.getPaymentMethodsByRecharge(isH5, UserPool.getUser()));
    }


    @ApiOperation(value = "绑卡支付发送短信", notes = "绑卡支付发送短信", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/bindPaySendSms", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<BindPaySendSmsVO> bindPaySendSms(@Valid @RequestBody BindPaySendSmsRequest request, HttpServletRequest httpServletRequest) {
        return Result.fail("功能已更新,请下载最新版本APP");
    }

    @ApiOperation(value = "绑卡支付原石订单发送短信", notes = "绑卡支付原石订单发送短信", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/bindRoughStoneSendSms", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<BindPaySendSmsVO> bindRoughStoneSendSms(@Valid @RequestBody BindPaySendSmsRequest request, HttpServletRequest httpServletRequest) {
        return Result.fail("功能已更新,请下载最新版本APP");
    }

    @ApiOperation(value = "杉德余额原石支付", notes = "杉德余额原石支付", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/sandeRoughStoneSend", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result sandeRoughStoneSend(@Valid @RequestBody PaymentRequest request, HttpServletRequest httpServletRequest) {
        return Result.fail("功能已更新,请下载最新版本APP");
    }

    @ApiOperation(value = "绑卡支付发送短信（二级）", notes = "绑卡支付发送短信（二级）", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/bindPaySendSmsSecond", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<BindPaySendSmsVO> bindPaySendSmsSecond(@Valid @RequestBody BindPaySendSmsSecondRequest request, HttpServletRequest httpServletRequest) {
        return Result.fail("功能已更新,请下载最新版本APP");

    }

    @ApiOperation(value = "绑卡支付短信认证", notes = "绑卡支付短信认证", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/bindPay", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result bindPay(@Valid @RequestBody BindPayRequest request, HttpServletRequest httpServletRequest) {
        return Result.fail("功能已更新,请下载最新版本APP");

    }

    @ApiOperation(value = "唤起支付（首发）", notes = "唤起支付（首发）", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/getPay", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<GetPaySignVO> getPay(@Valid @RequestBody PaymentRequest request, HttpServletRequest httpServletRequest) {
        return Result.success(payOrderService.getPay(request.getPaymentMethod(), request.getOrderId(), request.getBankCardId(), UserPool.getUser(), ServletUtil.getClientIP(httpServletRequest), request.getMac(), request.getWebPay(), request.getJumpType()));
    }


    //TODO 快捷支付申请短信  6.3.6-pay
    @ApiOperation(value = "唤起支付（大厅）", notes = "唤起支付（大厅）", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/getPaySecond", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<GetPaySignVO> getPay(@Valid @RequestBody PaymentSecondRequest request, HttpServletRequest httpServletRequest) {
        GetPaySignVO vo = null;
        switch (request.getOrderType()) {
            case COLLECTION:
                vo = payOrderService.getPaySecond(request.getPaymentMethod(), request.getOrderIds(), request.getBankCardId(),
                        UserPool.getUser(), ServletUtil.getClientIP(httpServletRequest), request.getMac(), request.getWebPay(), request.getPassword(), request.getRandomKey());
                break;
            case EQUITY_PROPS:
                vo = payOrderService.getPayProps(request.getPaymentMethod(), request.getOrderIds(), request.getBankCardId(),
                        UserPool.getUser(), ServletUtil.getClientIP(httpServletRequest), request.getMac(), request.getWebPay(), request.getPassword(), request.getRandomKey());
                break;
            default:
                return Result.fail("支付类型不正确");
        }
        return Result.success(vo);
    }


    @ApiOperation(value = "唤起支付（求购）", notes = "唤起支付（求购）", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/gePayWantBuy", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<GetPaySignVO> gePayWantBuy(@Valid @RequestBody PaymentRequest request, HttpServletRequest httpServletRequest) {
        GetPaySignVO vo = null;
        return Result.success(payOrderService.getPayWantBuy(request.getPaymentMethod(), request.getOrderId(), request.getBankCardId(),
                UserPool.getUser(), ServletUtil.getClientIP(httpServletRequest), request.getMac(), request.getWebPay(),
                request.getJumpType(), request.getPassword(), request.getRandomKey()));
    }


    @ApiOperation(value = "唤起支付（集售）", notes = "唤起支付（集售）", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/gePayCollective", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<GetPaySignVO> gePayCollective(@Valid @RequestBody PaymentCollectiveRequest request, HttpServletRequest httpServletRequest) {
        GetPaySignVO vo = null;
        return Result.success(payOrderService.getPayCollective(request.getPaymentMethod(), request.getOrderIds(),
                request.getBankCardId(), UserPool.getUser(), ServletUtil.getClientIP(httpServletRequest), request.getMac(),
                request.getWebPay(), request.getJumpType(), request.getPassword(), request.getRandomKey()));
    }

    @ApiOperation(value = "唤起支付（分解藏品）", notes = "唤起支付（分解藏品）", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/getPayRough", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<GetPaySignVO> getPayRough(@Valid @RequestBody PaymentRequest request, HttpServletRequest httpServletRequest) {
        return Result.success(payOrderService.getPayRough(request.getPaymentMethod(), request.getOrderId(), request.getBankCardId(), UserPool.getUser(), ServletUtil.getClientIP(httpServletRequest), request.getMac(), request.getWebPay(), request.getJumpType()));

    }

    @ApiOperation(value = "唤起支付（名片购买）", notes = "唤起支付（名片购买）", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/getPayBusinessCard", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<GetPaySignVO> getPayBusinessCard(@Valid @RequestBody PaymentRequest request, HttpServletRequest httpServletRequest) {
        return Result.success(payOrderService.getPayBusinessCard(request.getPaymentMethod(), request.getOrderId(), request.getBankCardId(), UserPool.getUser(), ServletUtil.getClientIP(httpServletRequest), request.getMac(), request.getWebPay(), request.getJumpType()));

    }

    @ApiOperation(value = "查询是否支付成功", notes = "查询是否支付成功", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/getPayResult", produces = MediaType.APPLICATION_JSON_VALUE)
    public Result getPayResult(@Valid @RequestBody OrderNoRequest request) {
        try {
            Thread.sleep(500);//延迟一下是为了防止查询结果比支付回调先到
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return Result.success(payOrderService.getPayOrderStatus(request.getOrderNo()));
    }


    @ApiOperation(value = "衫德支付回调", notes = "衫德支付回调", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/sandFastNotify", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiIgnore
    @WithoutSign
    public String sandFastNotify(HttpServletRequest request) throws GlobalException {
        String result = URLDecoder.decode(new RequestWrapper(request).getBody(), Charset.defaultCharset());
        log.info("sand fast notify back {}", result);
        Map<String, String> params = analyticalParameters(result);
        String data = params.get("data");
        JSONObject head = JSON.parseObject(data).getJSONObject("head");
        JSONObject body = JSON.parseObject(data).getJSONObject("body");
        RLock lock = redisson.getLock(RedisKeyEnum.PAY_SUCCESS_LOCK.getKey() + body.getString("orderCode"));
        try {
            boolean res = lock.tryLock(30, TimeUnit.SECONDS);
            if (res) {
                if (StrUtil.equals(head.getString("respCode"), "000000")) {
                    payOrderService.orderPaySuccess(payOrderDao.getByTradeNo(body.getString("orderCode")), body.getString("payTime"), result);
                } else {
                    log.warn("order pay fail:{}", body.getString("tradeNo"));
                }
                return "respCode=000000";
            }
        } catch (InterruptedException e) {
            throw new GlobalException("系统超时");
        } finally {
            lock.unlock();
        }
        return "FAIL";
    }


    @ApiOperation(value = "汇付支付回调", notes = "汇付支付回调", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/HfNotify", produces = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    @WithoutSign
    public String hfFastNotify(HttpServletRequest request) throws GlobalException {
        String result = URLDecoder.decode(new RequestWrapper(request).getBody(), Charset.defaultCharset());
        String str = HfPayHelper.parseResult(result.replaceAll("check_value=", ""));
        log.info("huifu fast notify back {}", str);
        HfPayNotifyRequest hfReq = JSONObject.parseObject(str, HfPayNotifyRequest.class);
        RLock lock = redisson.getLock(RedisKeyEnum.PAY_SUCCESS_LOCK.getKey() + hfReq.getOrder_id());
        try {
            boolean res = lock.tryLock(30, TimeUnit.SECONDS);
            if (res) {
                if (StrUtil.equals(hfReq.getResp_code(), "C00000") && StrUtil.equals(hfReq.getTrans_stat(), "S")) {
                    payOrderService.orderPaySuccess(payOrderDao.getByTradeNo(hfReq.getOrder_id()), DateTime.now().toString("yyyyMMddHHmmss"), str);
                } else {
                    log.warn("order pay fail:{}", hfReq.getOrder_id());
                }
                return "SUCCESS";
            }
        } catch (InterruptedException e) {
            throw new GlobalException("系统超时");
        } finally {
            lock.unlock();
        }
        return "FAIL";
    }


    @ApiOperation(value = "苹果支付", notes = "苹果支付", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/applePay", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    @ApiIgnore
    public Result applePay(@Valid @RequestBody ApplePayRequest request, HttpServletRequest httpServletRequest) throws GlobalException {
        RLock lock = redisson.getLock(RedisKeyEnum.APPLE_PAY_LOCK.getKey() + request.getOrderId());
        try {
            boolean res = lock.tryLock(10, 10, TimeUnit.SECONDS);
            if (res) {
                payOrderService.applePay(request.getOrderId(), request.getReceiptData(), request.getIsSandBox(), getRemoteHost(httpServletRequest));
            }
        } catch (InterruptedException e) {
            throw new GlobalException("系统超时");
        } finally {
            lock.unlock();
        }
        return Result.success();
    }


    @ApiOperation(value = "汇付支付开户回调", notes = "汇付支付开户回调", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/accountNotifyUrl", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiIgnore
    @WithoutSign
    public String accountNotifyUrl(HttpServletRequest request) throws GlobalException {
        String result = URLDecoder.decode(new RequestWrapper(request).getBody(), Charset.defaultCharset());
        String str = HfPayHelper.parseResult(result.replaceAll("check_value=", ""));
        log.info("huifu open account notify back {}", str);

        HfAccountNotifyRequest hfReq = JSONObject.parseObject(str, HfAccountNotifyRequest.class);

        if (StrUtil.equals(hfReq.getResp_code(), "C00000")) {
            payOrderService.hfOpenNotify(hfReq.getUser_id(), hfReq.getUser_cust_id(), hfReq.getAcct_id());
        } else {
            log.warn("huifu open account fail:{}", hfReq.getOrder_id());
        }
        return "SUCCESS";
    }


    @ApiOperation(value = "系统钱包支付", notes = "系统钱包支付", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/walletPay", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result walletPay(@Valid @RequestBody WalletPayRequest request, HttpServletRequest httpServletRequest) throws GlobalException {
        return Result.fail("请升级到最新版本");
//        UserInfo user = UserPool.getUser();
////        checkParameterService.CheckVerificationcode(user.getUserTel(),
////                request.getSmsId(),
////                request.getCodes(),
////                SendSMSEnum.WALLET_PAY.getCode());
//
//        if(!StrUtil.equals( request.getDealPwd(),user.getTransactionPassword())){
//            return Result.fail(ErrorCode.PASSWORD_ERROR);
//        }
//        RLock lock = redisson.getLock(RedisKeyEnum.WALLET_PAY_LOCK.getKey() + request.getOrderId());
//        try {
//            boolean res = lock.tryLock(3, TimeUnit.SECONDS);
//            if (res) {
//                payOrderService.walletPay(request.getPaymentMethod(), request.getOrderId(), user, ServletUtil.getClientIP(httpServletRequest));
//            }
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//            throw new GlobalException("系统超时");
//        } finally {
//            lock.unlock();
//        }
//        return Result.success();
    }

    //TODO 绑卡支付验证 6.3.6-pay
    @ApiOperation(value = "支付验证", notes = "支付验证", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/verifyPay", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result verifyPay(@Valid @RequestBody VerifyPayRequest request, HttpServletRequest httpServletRequest) throws GlobalException {
        UserInfo user = UserPool.getUser();
        RLock lock = redisson.getLock(RedisKeyEnum.WALLET_PAY_LOCK.getKey() + request.getOrderId());
        try {
            boolean res = lock.tryLock(30, TimeUnit.SECONDS);
            if (res) {
                payOrderService.verifyPay(user, request.getOrderId(), request.getDealPwd(), request.getVerifyCode(), request.getToken());
            }
        } catch (InterruptedException e) {
            throw new GlobalException("系统超时");
        } finally {
            lock.unlock();
        }
        return Result.success();
    }

    @ApiOperation(value = "获取用户三方支付待结算金额", notes = "获取用户三方支付待结算金额", httpMethod = "POST",
            produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/getUserUnsettle", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<UserOrderAccountFlowVO> getUserOrderAccountFlow(@Valid @RequestBody UserOrderAccountFlowRequest request) {
        return Result.success(userAccountFlowService.findByAPayChannel(request.getPayChannelEnum()));
    }

    @ApiOperation(value = "查询三方钱包进出账明细", notes = "查询三方钱包进出账明细", httpMethod = "POST",
            produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/getBalanceDetailPage", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<PayBalanceDetailVO> getBalanceDetailPage(@Valid @RequestBody PayWalletDetailRequest request) {
        //参数校验
        validWalletDetailReq(request);

        return Result.success(userAccountFlowService.getPayBalanceDetail(request.getPayChannelEnum(),
                request.getStartTime(), request.getFinishTime(), request.getChangeType(), request.getPageNo(), request.getPageSize()));
    }

    @ApiOperation(value = "通用支付方式", notes = "通用支付方式", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/commonPaymentMethods", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<List<PaymentMethodVO>> commonPaymentMethods(@Valid @RequestBody CommonPaymentDTO request) {
        return Result.success(paymentMethodService.commonPaymentMethods(request));
    }

    /**
     * 解析回调参数
     *
     * @param params
     * @return
     */
    public Map<String, String> analyticalParameters(String params) {
        if (StrUtil.isNotBlank(params)) {
            Map<String, String> paramsMap = Maps.newHashMap();
            for (String str : params.split("&")) {
                String[] s = str.split("=");
                if (s.length == 2) {
                    paramsMap.put(s[0], s[1]);
                } else {
                    paramsMap.put(s[0], StrUtil.EMPTY);
                }
            }
            return paramsMap;
        }
        return null;
    }


    /**
     * 钱包明细查询校验
     *
     * @param request
     */
    public void validWalletDetailReq(PayWalletDetailRequest request) {
        //公共参数校验
        Assert.isTrue(null != request.getPayChannelEnum(), () -> new GlobalRunTimeException(ErrorCode.PAY_CHANNEL_CANT_BE_NULL));
        Assert.isTrue((null != request.getPageNo() && null != request.getPageSize()),
                () -> new GlobalRunTimeException(ErrorCode.PAGE_PARAMS_CANT_BE_NULL));
        Assert.isTrue(request.getPageNo() >= 1, () -> new GlobalRunTimeException(ErrorCode.PAGE_NO_MUST_START_1));
        if (null == request.getFinishTime()) {
            request.setFinishTime(DateTime.now());
        }

        //三方专用参数校验
        switch (request.getPayChannelEnum()) {
            case SAND:
                if (null == request.getStartTime()) {
                    request.setStartTime(DateUtil.offsetDay(request.getFinishTime(), -7));
                }

                Assert.isTrue(DateUtil.between(request.getStartTime(), request.getFinishTime(), DateUnit.DAY) <= 7L,
                        () -> new GlobalRunTimeException(ErrorCode.SAND_BALANCE_QUERY_CANT_GRANT_7_DAYS));
                Assert.isTrue(request.getPageSize() <= 50, () -> new GlobalRunTimeException(ErrorCode.SAND_BALANCE_DETAIL_CANT_QUERY_GRANT_50));

                break;
            case LL_PAY:
                if (null == request.getStartTime()) {
                    //连连最大查询一年内 精确到秒，因远程调用可能存在时延，所以故意少查1分钟
                    request.setStartTime(DateUtil.offsetMonth(request.getFinishTime(), -3));
                }
                Assert.isTrue(request.getStartTime().after(DateUtil.offsetMonth(new Date(), -12)),
                        () -> new GlobalRunTimeException(ErrorCode.LL_BALANCE_QUERY_CANT_QUERY_BEFORE_1_YEAR));
                Assert.isTrue(request.getPageSize() <= 10, () -> new GlobalRunTimeException(ErrorCode.LL_BALANCE_DETAIL_CANT_QUERY_GRANT_10));
                break;
            default:
                throw new RuntimeException("暂不支持");
        }

    }

    private String getRemoteHost(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip.equals("0:0:0:0:0:0:0:1") ? "127.0.0.1" : ip;
    }
}


